package cn.edu.scnu.springbootcinema.service;

import cn.edu.scnu.springbootcinema.entity.Movie;
import cn.edu.scnu.springbootcinema.entity.RankingVO;
import cn.edu.scnu.springbootcinema.entity.RegionMovieCount;
import cn.edu.scnu.springbootcinema.mapper.MovieMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;

@Service
public class MovieService extends ServiceImpl<MovieMapper,Movie> {

    @Resource
    private MovieMapper movieMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    public Movie findMovieById(Integer movieId) {
        String redisKey = "movie:" + movieId;
        Movie movie = (Movie) redisTemplate.opsForValue().get(redisKey);
        if (movie == null) {
            movie = movieMapper.selectById(movieId);
            if (movie != null) {
                redisTemplate.opsForValue().set(redisKey, movie);
            }
        }
        return movie;
    }

    public List<Movie> getAllMovies() {
        List<Movie> cachedMovies = (List<Movie>) redisTemplate.opsForValue().get("allMovies");
        if (cachedMovies != null) {
            return cachedMovies;
        }else {
            List<Movie> movies = this.list();
            redisTemplate.opsForValue().set("allMovies", movies);
            return movies;
        }
    }

    private List<Movie> getCachedOrQueryMovies(String cacheKey, String orderByColumn) {
        List<Movie> cachedMovies = (List<Movie>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedMovies != null) {
            return cachedMovies;
        } else {
            QueryWrapper<Movie> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByDesc(orderByColumn).last("limit 10");
            List<Movie> movies = movieMapper.selectList(queryWrapper);
            redisTemplate.opsForValue().set(cacheKey, movies);
            return movies;
        }
    }

    public List<Movie> getRelatedMovies(Integer currentMovieId, String type) {
        return baseMapper.selectList(
                new QueryWrapper<Movie>()
                        .select("id, title, cover_url, rating, type")
                        .eq("type", type)
                        .ne("id", currentMovieId)
                        .orderByDesc("rating")
                        .last("LIMIT 8") // 限制最多推荐8部
        );
    }

    public List<Movie> getHotMovies() {
        return getCachedOrQueryMovies("hotMovies", "rating");
    }

    public List<Movie> getLatestMovies() {
        return getCachedOrQueryMovies("latestMovies", "release_date");
    }

    public List<RegionMovieCount> getRegionMovieCount() {
        return movieMapper.getRegionMovieCount();
    }

    public List<RankingVO> getWeeklyRankings() {
        LocalDate currentDate = LocalDate.now();

        // 获取本周的最后一天（周日）
        LocalDate lastDayOfWeek = currentDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        List<Movie> movieList = query()
                .le("release_date", lastDayOfWeek)
                .ge("release_date", lastDayOfWeek.minusDays(6))
                .orderByDesc("view_count")
                .list();

        return movieList.stream().map(movie ->
                new RankingVO(movie.getId(), movie.getTitle(), movie.getCoverUrl(), movie.getRating(), movie.getReleaseDate().getYear()+1900)).toList();
    }

    public List<RankingVO> getMonthlyRankings() {
        //获取本月的电影
        LocalDate currentDate = LocalDate.now();
        //获取本月最后一天
        LocalDate lastDayOfMonth = currentDate.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println(lastDayOfMonth);
        //获取本月第一天
        LocalDate firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth());
        List<Movie> movieList = query()
                .ge("release_date", firstDayOfMonth)
                .le("release_date", lastDayOfMonth)
                .orderByDesc("view_count")
                .list();
        return movieList.stream().map(movie ->
                new RankingVO(movie.getId(), movie.getTitle(), movie.getCoverUrl(), movie.getRating(), movie.getReleaseDate().getYear()+1900)).toList();
    }

    public List<RankingVO> getAllTimeRankings() {
        List<Movie> movieList = query()
                .orderByDesc("view_count")
                .list();

        return movieList.stream().map(movie ->
                new RankingVO(movie.getId(), movie.getTitle(), movie.getCoverUrl(), movie.getRating(), movie.getReleaseDate().getYear()+1900)).toList();
    }

    public List<RankingVO> getTopRatedRankings() {
        List<Movie> movieList = query()
                .orderByDesc("rating")
                .list();
        return movieList.stream().map(movie ->
                new RankingVO(movie.getId(), movie.getTitle(), movie.getCoverUrl(), movie.getRating(), movie.getReleaseDate().getYear()+1900)).toList();
    }

    public List<Movie> searchByQuery(String query) {
        return movieMapper.searchByQuery(query);
    }
}